<?php
require_once(dirname(__FILE__)."/../common/constants.php");
require_once(DB_SESSION_DIR_PATH."/db_operator.php");
require_once(DB_SESSION_DIR_PATH."/db_obj_defs.php");
require_once(TRANSACTIONS_DIR_PATH."/teammembermanager.php");
require_once(TRANSACTIONS_DIR_PATH."/matchrequestmanager.php");
require_once(TRANSACTIONS_DIR_PATH."/matchdirectrequestmanager.php");
require_once(TRANSACTIONS_DIR_PATH."/trans_common.php");

/*
 * Created on 2007-11-27
 * Author: William
 */
class TeamManager extends Team {
	public function register() {
		/*
		 * Validate the user name provided.
		 */
		$bInUse = TeamManager::is_team_name_in_use($this->name);
		if ($bInUse)
			return TeamRegStat::NAME_IN_USE;
		
		
		$team_uid = parent::register(CONFIGURATION_DIR_PATH."/create_team.xml",
									 TRUE);
									 
		if ($team_uid === -1)
			return TeamRegStat::INTERNAL_ERROR;
		
		$tm_mgr = new TeamMemberManager($team_uid, $this->captainid);
		$stat = $tm_mgr->register();
		
		if($stat === -1) {
			return TeamRegStat::INTERNAL_ERROR;
		}
		
		return $team_uid;
	}
	
	/*
	 * Check whether the team name is available.
	 */
	public static function is_team_name_in_use($name) {
		$db_opera = new DatabaseOperator();
		$db_opera->config(CONFIGURATION_DIR_PATH."/team_table.xml");
		$cList = new SqlCondList();
		$cList->add_condition(new SqlCondition("name", SqlCondition::EQUAL, $name));	
		$tms = $db_opera->select($cList);
		if (count($tms) > 0)
			return TRUE;
		else
			return FALSE;
	}
	
	/*
	 * Change this object represented team's captain to the one who is represented by $new_captain_id.
	 */
	public static function change_captain($team_uid, $new_captain_id) {
		// Check if he is a team member first.
		$stat = TeamManager::is_team_member($team_uid, $new_captain_id);
		if ($stat === FALSE)
			return $stat;
			
		$operator = new DatabaseOperator();
		$operator->config(CONFIGURATION_DIR_PATH."/team_table.xml");
		
		$info = array();
		$info['captainid'] = $new_captain_id;
		
		$condList = new SqlCondList();
		$condList->add_condition(new SqlCondition('uid', SqlCondition::EQUAL, $team_uid));
		$stat = $operator->update($info, $condList);
		if (DbError::is_error($stat))
			return FALSE;
		else 
			return TRUE;
	}
	
	public function update_info() {
		$operator = new DatabaseOperator();
		$operator->config(CONFIGURATION_DIR_PATH."/team_table.xml");
		
		$info = $this->toArray();
		
		$stat = DbError::NO_DB_OPERATION_NEEDED;
		if (count($info)) {
			$condList = new SqlCondList();
			$condList->add_condition(new SqlCondition('uid', SqlCondition::EQUAL, $this->uid));
			$stat = $operator->update($info, $condList);
		}
		
		return $stat;
	}
	
	public static function deregister($team_uid) {
		$operator = new DatabaseOperator();
		$operator->config(CONFIGURATION_DIR_PATH."/team_member_table.xml");
		
		$c1 = new SqlCondition("teamid", SqlCondition::EQUAL, $team_uid);
		$cList = new SqlCondList();
		$cList->add_condition($c1);
		$db_stat = $operator->delete($cList);
		
		if ($db_stat != DbError::DB_OK)
			return FALSE;
			
		$operator->config(CONFIGURATION_DIR_PATH."/team_table.xml");
		$c1 = new SqlCondition("uid", SqlCondition::EQUAL, $team_uid);
		$cList = new SqlCondList();
		$cList->add_condition($c1);		
		$db_stat = $operator->delete($cList);
		return DbError::is_error($db_stat);
	}
	
	/* Note, you, as a team, challenge a match. So:
	 * 1. Construct a MatchRequestManager object.
	 * 2. Make a match request by invoking the above constructed object's register() method.
	 * 
	 * Parameter:
	 * $team_id: identify the team which wants to challenge.
	 * $match_id: identify the match that someone created before, and is waiting for the challenge.
	 * 
	 * Return value:
	 * If match request is sent, TRUE is returned; otherwise, FALSE is returned.
	 */
	public static function challenge($team_id, $match_id) {
		$mr_mngr = new MatchRequestManager($team_id, $match_id, MatchRequestStat::REQ_WAIT_FOR_ACPT);
		$stat = $mr_mngr->register();
		return $stat;
	}
	
	/*
	 * Parameter:
	 * $team_uid: identify the team who makes the direct request.
	 * $rival_team_uid: identify the rival team.
	 * $match_name: identify the customized match name.
	 * 
	 * Return value: if operations succeeds, return the match ID generated automatically. Otherwise, FALSE
	 * is returned.
	 */
	public static function make_direct_request(	$team_uid,
												$team_name,
											 	$rival_team_uid,
											 	$match_name, 
											 	$playdate = NULL, 
											 	$field = NULL, 
											 	$fee = NULL) {
		/*
		 * Create a match first.
		 */
		$match_manager = new MatchManager($match_name,
										  $team_uid,
										  $team_name,
										  GetCurrentDateTime2DbFormat(),
										  MatchStatus::MATCH_CREATED,
										  MatchProperty::MATCH_PRIVATE,
										  $playdate,
										  $rival_team_uid,
										  $field,
										  $fee);
		/*
		 * additonal setting for rival.
		 */
		$match_manager->rival = $rival_team_uid;
		$match_id = $match_manager->register();
		
		if ($match_id === MatchRegStat::INTERNAL_ERROR)
			return DbError::INSERT_ERROR;
		
		/*
		 * Make a direct match request.
		 */
		$mdr_mngr = new MatchDirectRequestManager($rival_team_uid,
												  $team_uid, 
												  $match_id,
												  MatchDirectRequestStat::REQ_WAIT_FOR_ACPT);
		$stat = $mdr_mngr->register();
		if (DbError::is_error($stat)) {
			return $stat;
		} else
			return $match_id;
	}
	
	/*
	 * To invoke this function, only team's UID is required.
	 * Return value: an array containing MatchDirectRequest typed objects.
	 */
	public static function show_direct_match_request($team_uid) {
		$opera = new DatabaseOperator();
		$opera->config(CONFIGURATION_DIR_PATH."/match_direct_request_table.xml");
		
		$cList = new SqlCondList();
		$cList->add_condition(new SqlCondition("requesteeid",
											   SqlCondition::EQUAL,
											   $team_uid));
		
		$mdrs = $opera->select($cList);
		
		$ret = array();
		if (count($mdrs)) {
			// Direct match requests exist.
			$mdr_stub = new MatchDirectRequest();
			foreach ($mdrs as $m) {
				$ret[] = $mdr_stub->clone2object($m);
			}
		}
		
		return $ret;
	}
	
	/*
	 * To answer the direct match request, if the request is accepted, update the match status to accepted;
	 * if rejected, update to cancelled.
	 * 
	 * If one user tries to check the direct match request status which is made by himself, just query all the
	 * direct match requests and check all the status of the corresponding matches.
	 * 
	 * Parameter:
	 * $myteam_uid: the UID of the team to which any other teams make direct match requests to.
	 * $match_uid: the match UID that the direct match request corresponds to.
	 * $ack: accepted or rejected.
	 * 
	 * Return value:
	 * TRUE if database operation succeeds; otherwise FALSE.
	 */
	public static function reply_direct_match_request($myteam_uid, $match_uid, $ack) {
		if (!MatchRequestStat::is_valid($ack)) {
			echo "Invalid acknowledgement.";
			return FALSE;
		}
		
		$opera = new DatabaseOperator();
		$opera->config(CONFIGURATION_DIR_PATH."/match_table.xml");
		
		$cList = new SqlCondList();
		$cList->add_condition(new SqlCondition("uid",
											   SqlCondition::EQUAL,
											   $match_uid));
												   
		$info = array();
		$info["rival"] = $myteam_uid;
		$info["status"] = $ack;
		$stat = $opera->update($info, $cList);
		
		return DbError::is_error($stat);
	}
	/*
	 * Parameter:
	 * $team_uid: the team uid identifying the team who wants to invite a player.
	 * $member2invite_uid: uid of the member whom the team wants to invite.
	 * 
	 * Return value:
	 * TRUE if the inviting request is sent successfully, otherwise FALSE.
	 */
	public static function invite($team_uid, $member2invite_uid) {
		$mir_mngr = new MemberInviteRequestManager($member2invite_uid,
												   $team_uid, 
												   MemberInviteRequestStat::REQ_SENT);
		$stat = $mir_mngr->register();
		return DbError::is_error($stat);
	}
	
	public static function is_team_member($team_uid, $member_uid) {
		$opera = new DatabaseOperator();
		$opera->config(CONFIGURATION_DIR_PATH."/team_member_table.xml");
		
		$cList = new SqlCondList();
		$cList->add_condition(new SqlCondition("teamid",
											   SqlCondition::EQUAL,
											   $team_uid));
		$cList->add_relation(SqlCondition::_AND);
		$cList->add_condition(new SqlCondition("memberid",
											   SqlCondition::EQUAL,
											   $member_uid));
		$info[] = "count(*)";
		$ret = $opera->select($cList, $info);
		return DbTools::check_count_result($ret, 1);
	}
	
	public function update_record($result) {
		$t_objs = TeamManager::query_by_uids($this->uid);
		
		if ($t_objs == null || count($t_objs) != 1)
			return FALSE;
		
		$t_obj = $t_objs[0];
		$delegate = new TeamManager();
		$delegate->uid = $this->uid;
		$total = $t_obj->win + $t_obj->draw + $t_obj->lose + 1;
		
		if ($result == Team::WIN)
			$delegate->win = $t_obj->win + 1;
		else if ($result == Team::DRAW)
			$delegate->draw = $t_obj->draw + 1;
		else if ($result == Team::LOSE)
			$delegate->lose = $t_obj->lose + 1;

		$delegate->win_pct = round( ($t_obj->win / $total) , 2 );
		
		$stat = $delegate->update_info();
		
		return (!DbError::is_error($stat));
	}
	
	/*
	 * List current team list.
	 */
	public static function query_team_list($condition_list) {
		$op = new DatabaseOperator();
		$op->config(CONFIGURATION_DIR_PATH."/team_table.xml");
		$ret_array = $op->select($condition_list);
		
		$return_val = array();
		$team_obj = new Team();
		foreach ($ret_array as $item) {
			$return_val[] = $team_obj->array2copy($item);
		}
		
		return $return_val;
	}
	
	/*
	 * Query all the team members in one team specified by $team_uid.
	 * 
	 * Parameter:
	 * $team_uid: specify the team whose members are to be queried, or an array containing a list of team UIDs.
	 * 
	 * Return value:
	 * An array containing some User objects which contain the members information.
	 * Key: team UID
	 * Value: team member objects.
	 */
	public static function query_team_member($team_uid) {
		$op = new DatabaseOperator();
		$op->config(CONFIGURATION_DIR_PATH."/team_member_table.xml");
		
		$it_array = array();
		if (gettype($team_uid) == gettype(array()))
			$it_array = $team_uid;
		else
			$it_array[] = $team_uid;
		
		$ret_map = array(); // key -> team UID, value-> a list of member objects
		
		foreach ($it_array as $t_uid) {
			$cList = new SqlCondList();
			$cList->add_condition(new SqlCondition("teamid",
												   SqlCondition::EQUAL,
												   $t_uid));
													   
			$info[] = "memberid";
			
			$ret_array = $op->select($cList, $info);
			
			$op->config(CONFIGURATION_DIR_PATH."/user_table.xml");
			$user_obj = new User();
			$mbr_obj_list = array();
			foreach ($ret_array as $row) {
				$user_uid = $row["memberid"];
				
				$cList = new SqlCondList();
				$cList->add_condition(new SqlCondition("uid",
												   SqlCondition::EQUAL,
												   $user_uid));
												   
				$ret = $op->select($cList);
				$mbr_obj_list[] = $user_obj->array2copy($ret[0]);
			}
			
			$ret_map[$t_uid] = $mbr_obj_list;
		}
		
		return $ret_map;
	}
	
	public function query_by_uids($uid) {
		/*
		 * Query information by the UID specified by $uid.
		 */
		
		$rows = parent::query_by_uids(CONFIGURATION_DIR_PATH."/team_table.xml", $uid);
		if ($rows === NULL) {
			return NULL;
		} else {
			$ret = array();
			
			$team_delegate = new Team();
			if ($rows != null && count($rows) > 0) {
				foreach ($rows as $row) {
					$tmp = $team_delegate->array2copy($row);
					$ret[] = $tmp;
				}
			}
			
			return $ret;
		}
	}
	
	/*
	 * Parameter:
	 * $team_uid: the team's UID to which the members' will be added.
	 * $member_uids: the members' UIDs that will be added into the team.
	 * 
	 * Return value:
	 * An array: contains the memebers fail to add to the team.
	 */
	public static function add_team_members($team_uid, $member_uids) {
		if ($member_uids === NULL || (gettype($member_uids) == gettype(array()) && count($member_uids) == 0))
			return array();
		
		if (gettype($member_uids) != gettype(array())) {
			$tmp = $member_uids;
			$member_uids = array();
			$member_uids[] = $tmp;
		}
		
		$ret = array();
		foreach ($member_uids as $mem_uid) {
			$tm_mgr = new TeamMemberManager($team_uid, $mem_uid);
			$stat = $tm_mgr->register();
			if (DbError::is_error($stat))
				$ret[] = $mem_uid;
		}
		return $ret;
	}
	
	/*
	 * Parameter:
	 * $team_uid: the team's UID from which the members' will be deleted.
	 * $member_uids: the members' UIDs that will be deleted from the team.
	 * 
	 * Return value:
	 * An array: contains the memebers fail to delete from the team.
	 */
	public static function delete_team_members($team_uid, $member_uids) {
		if ($member_uids === NULL || count($member_uids) == 0)
			return array();
		
		$tmp = $member_uids;
		if (gettype($member_uids) != gettype(array())) {
			$member_uids = array();
			$member_uids[] = $tmp;
		}
		$ret = array();
		foreach ($member_uids as $mem_uid) {
			$stat = TeamMemberManager::delete_member($team_uid, $mem_uid);
			if ($stat == FALSE)
				$ret[] = $mem_uid;
		}
		return $ret;
	}
	
	/*
	 * Parameter:
	 * $by :        0 - By ID
	 * 		1 - By winning percentage
	 */
	public static function getTop($top, $by = 1) {
		$opera = new DatabaseOperator();
		$opera->config(CONFIGURATION_DIR_PATH."/team_table.xml");
		
		$cList = new SqlCondList();
		
		if ($by == 1)
			$cList->add_constraint(new SqlConstraint(SqlConstraint::ORDERBY, "win_pct"));
		else
			$cList->add_constraint(new SqlConstraint(SqlConstraint::ORDERBY, "uid"));
			
		$cList->add_sort(new SqlSort(SqlSort::DESC));
		$cList->add_limit(new SqlLimit(0, $top));
		
		$rows = $opera->select($cList);
		
		$ret = array();
			
		$team_delegate = new Team();
		if ($rows != null && count($rows) > 0) {
			foreach ($rows as $row) {
				$tmp = $team_delegate->array2copy($row);
				$ret[] = $tmp;
			}
		}
		return $ret;
	}
}
?>
